package cn.xiaopengstack.trigger.http;

import cn.xiaopengstack.api.dto.*;
import cn.xiaopengstack.api.service.IMarketTradeService;
import cn.xiaopengstack.domain.activity.model.entity.MarketProductEntity;
import cn.xiaopengstack.domain.activity.model.entity.TrialCalculateEntity;
import cn.xiaopengstack.domain.activity.service.trialcal.IIndexGroupBuyMarketService;
import cn.xiaopengstack.domain.trade.model.entity.*;
import cn.xiaopengstack.domain.trade.model.valobj.NotifyTypeEnum;
import cn.xiaopengstack.domain.trade.service.IRefundService;
import cn.xiaopengstack.domain.trade.service.ITradeLockOrderService;
import cn.xiaopengstack.domain.trade.service.ITradeSettlementOrderService;
import cn.xiaopengstack.types.enums.RedisKeyEnum;
import cn.xiaopengstack.types.enums.ResponseCode;
import cn.xiaopengstack.types.model.Response;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author jiangyangang
 */
@Slf4j
@RestController
@RequestMapping("/api/${app.config.api-version}/group-buy-market/trade/")
@CrossOrigin("*")
public class MarteTradeController implements IMarketTradeService {

    @Resource
    private IIndexGroupBuyMarketService indexTrialCalService;

    @Resource
    private ITradeLockOrderService groupBuyTradeService;

    @Resource
    private ITradeSettlementOrderService tradeSettlementOrderService;

    @Resource
    private IRefundService refundService;

    @Resource
    private RedissonClient redissonClient;

    @RequestMapping("lock_market_pay_order")
    @Override
    public Response<LockMarketOrderResponseDTO> lockGroupBuyMarketOrder(@RequestBody LockMarketOrderRequestDTO requestDTO) {
        log.info("营销交易锁单:{} LockMarketPayOrderRequestDTO:{}", requestDTO.getUserId(), JSONObject.toJSONString(requestDTO));
        RLock lock = redissonClient.getLock(RedisKeyEnum.trade_reentry_lock.getKey());
        try {
            boolean locked = lock.tryLock(3L, TimeUnit.SECONDS);
            if (!locked) {
                return Response.error(null, ResponseCode.REQUEST_TOO_FREQUENT);
            }

            // 查询
            Optional<MarketOrderEntity> marketOrderEntity = groupBuyTradeService.queryUnPayMarketPayOrder(requestDTO.getUserId(), requestDTO.getOutTradeNo());
            if (marketOrderEntity.isPresent()) {
                MarketOrderEntity marketOrder = marketOrderEntity.get();
                LockMarketOrderResponseDTO responseDTO = LockMarketOrderResponseDTO.builder()
                        .userId(requestDTO.getUserId())
                        .orderId(marketOrder.getOrderId())
                        .tradeOrderStatus(marketOrder.getStatusEnum().getStatus())
                        .build();
                return Response.success(responseDTO);
            }

            // 查询优惠
            MarketProductEntity marketProductEntity = MarketProductEntity.builder()
                    .channel(requestDTO.getChannel())
                    .source(requestDTO.getSource())
                    .userId(requestDTO.getUserId())
                    .goodsId(requestDTO.getGoodsId())
                    .activityId(requestDTO.getActivityId())
                    .build();
            TrialCalculateEntity trialCalculateEntity = indexTrialCalService.trialCalculate(marketProductEntity);

            // 锁单
//            String outTradeNo = RandomStringUtils.randomNumeric(12);
            MarketOrderEntity marketOrder = groupBuyTradeService.lockGroupBuyMarketOrder(
                    UserEntity.builder()
                            .userId(requestDTO.getUserId())
                            .build(),
                    PayActivityEntity.builder()
                            .activityId(requestDTO.getActivityId())
                            .teamId(StringUtils.isBlank(requestDTO.getTeamId()) ? RandomStringUtils.randomNumeric(8) : requestDTO.getTeamId())
                            .startTime(trialCalculateEntity.getStartTime())
                            .endTime(trialCalculateEntity.getEndTime())
                            .targetCount(trialCalculateEntity.getTargetCount())
                            .firstGroupBuy(StringUtils.isBlank(requestDTO.getTeamId()))
                            .build(),
                    PayDiscountEntity.builder()
                            .channel(requestDTO.getChannel())
                            .source(requestDTO.getSource())
                            // mock数据
                            .outTradeNo(requestDTO.getOutTradeNo())
                            .originalPrice(trialCalculateEntity.getOriginalPrice())
                            .goodsName(trialCalculateEntity.getGoodsName())
                            .goodsId(trialCalculateEntity.getGoodsId())
                            .deductionPrice(trialCalculateEntity.getDeductionPrice())
                            .build()
            );
            log.info("交易锁单记录(新):{} marketPayOrderEntity:{}", requestDTO.getUserId(), JSONObject.toJSONString(marketOrder));

            return Response.success(LockMarketOrderResponseDTO.builder()
                    .userId(marketOrder.getUserId())
                    .tradeOrderStatus(marketOrder.getStatusEnum().getStatus())
                    .orderId(marketOrder.getUserId())
                    .outTradeNo(marketOrder.getOutOrderNo())
                    .build());
        } catch (Exception e) {
            log.error("营销交易锁单服务失败:{} LockMarketPayOrderRequestDTO:{}", requestDTO.getUserId(), JSONObject.toJSONString(requestDTO), e);
            return Response.error(null, ResponseCode.UN_ERROR);
        } finally {
            lock.unlock();
        }
    }


    @RequestMapping("settlement_market_pay_order")
    @Override
    public Response<SettlementMarketOrderResponseDTO> settlementMarketPayOrder(@RequestBody SettlementMarketOrderRequestDTO requestDTO) {
        try {
            log.info("拼团订单结算开始, request={}", JSONObject.toJSONString(requestDTO));

            TradePaySuccessEntity tradePaySuccessEntity = TradePaySuccessEntity.builder()
                    .channel(requestDTO.getChannel())
                    .source(requestDTO.getSource())
                    .userId(requestDTO.getUserId())
                    // mock数据
                    .outTradeTime(new Date())
                    .outTradeNo(requestDTO.getOutTradeNo())
                    .notifyTypeEnum(NotifyTypeEnum.MQ)
                    .build();

            TradePaySettlementEntity tradePaySettlementEntity = tradeSettlementOrderService.settlementOrder(tradePaySuccessEntity);

            return Response.success(SettlementMarketOrderResponseDTO.builder()
                    .outTradeNo(requestDTO.getOutTradeNo())
                    .userId(requestDTO.getUserId())
                    .teamId(tradePaySettlementEntity.getTeamId())
                    .activityId(tradePaySettlementEntity.getActivityId())
                    .build());
        } catch (Exception e) {
            log.error("拼团订单结算异常, ", e);
            return Response.error(null, ResponseCode.UN_ERROR);
        }
    }


    /**
     * 拼团订单退款
     * @param requestDTO
     * @return
     */
    @RequestMapping("refund_order")
    @Override
    public Response<GroupBuyOrderRefundResponseDTO> refundOrder(@RequestBody GroupBuyOrderRefundRequestDTO requestDTO) {

        TradeRefundResponseEntity responseEntity = null;
        try {
            responseEntity = refundService.refund(
                    TradeRefundRequestEntity.builder()
                            .orderId(requestDTO.getOrderId())
                            .outRefundOrderId(StringUtils.isEmpty(requestDTO.getOutOrderId()) ? RandomStringUtils.randomNumeric(12) : requestDTO.getOutOrderId())
                            .userId(requestDTO.getUserId())
                            .refundOperator("User:" + requestDTO.getUserId())
                            .refundReason("User proactively refunds")
                            .build()
            );
        } catch (Exception e) {
            log.error("退款：退款出现异常!", e);
            return Response.error(null, ResponseCode.UN_ERROR);
        }

        return Response.success(GroupBuyOrderRefundResponseDTO
                .builder()
                        .refundOrderId(responseEntity.getRefundOrderId())
                        .refundStatus(responseEntity.getTradeRefundResponseStatusEnum().getCode())
                        .teamId(responseEntity.getTeamId())
                .build());
    }
}
